﻿using System;
using NUnit.Framework;
using NumSkull;

namespace NumSkullTests
{
    [TestFixture]
    [Category("Unit")]
    public class HistogramBinTests
    {
        [Test]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThrowsIfBoundsIsNull()
        {
            new HistogramBin(2d, null);
        }

        [Test]
        [ExpectedException(typeof(ArgumentOutOfRangeException))]
        public void ThrowsIfValueIsOutOfRange()
        {
            new HistogramBin(2d, new Bounds(5, 10));
        }

        [Test]
        public void AssignsValue()
        {
            var bin = new HistogramBin(2d);

            Assert.That(bin.Values.Contains(new HistogramBinValue(2)), Is.True);
        }

        [Test]
        public void AssignsBounds()
        {
            var bin = new HistogramBin(2d, new Bounds(0, 10));

            Assert.That(bin.Bounds, Is.EqualTo(new Bounds(0, 10)));
        }

        [Test]
        public void CalculatesSingleBounds()
        {
            var bin = new HistogramBin(2d);
            
            Assert.That(bin.Bounds, Is.EqualTo(new Bounds(2, 2)));
        }

        [Test]
        public void CalculatesSingleRange()
        {
            var bin = new HistogramBin(2d);
            
            Assert.That(bin.Range, Is.EqualTo(0));
        }

        [Test]
        public void UpdatesDynamicRangeOnRangedAdd()
        {
            var bin = new HistogramBin(2d, true);
            bin.Add(new[] {4, 5, 6, 3, 1d });
 
            Assert.That(bin.Range, Is.EqualTo(5));
        }

        [Test]
        public void UpdatesDynamicBoundsOnRangedAdd()
        {
            var bin = new HistogramBin(2d, true);
            bin.Add(new[] { 4, 5, 6, 3, 1d });

            Assert.That(bin.Bounds, Is.EqualTo(new Bounds(1, 6)));
        }

        [Test]
        public void DoesntUpdateStaticRangeOnRangedAdd()
        {
            var bin = new HistogramBin(2d);
            bin.Add(new[] { 4, 5, 6, 3, 1d });
            
            Assert.That(bin.Range, Is.EqualTo(0));
        }

        [Test]
        public void DoesntUpdateStaticBoundsOnRangedAdd()
        {
            var bin = new HistogramBin(2d);
            bin.Add(new[] { 4, 5, 6, 3, 1d });

            Assert.That(bin.Bounds, Is.EqualTo(new Bounds(2, 2)));
        }

        [Test]
        public void UpdatesDynamicRangeOnSingleAdd()
        {
            var bin = new HistogramBin(2d, true);
            bin.Add(1d);

            Assert.That(bin.Range, Is.EqualTo(1));
        }

        [Test]
        public void UpdatesDynamicBoundsOnSingleAdd()
        {
            var bin = new HistogramBin(2d, true);
            bin.Add(1d);

            Assert.That(bin.Bounds, Is.EqualTo(new Bounds(1, 2)));
        }

        [Test]
        public void DoesntUpdateStaticRangeOnSingleAdd()
        {
            var bin = new HistogramBin(2d);
            bin.Add(1d);
            
            Assert.That(bin.Range, Is.EqualTo(0));
        }

        [Test]
        public void DoesntUpdateStaticBoundsOnSingleAdd()
        {
            var bin = new HistogramBin(2d);
            bin.Add(1d);

            Assert.That(bin.Bounds, Is.EqualTo(new Bounds(2, 2)));
        }

        [Test]
        public void AddsRangedValuesOutsideOfDynamicBounds()
        {
            var bin = new HistogramBin(2d);
            bin.Add(new[] { 4, 5, 6, 3, 1d });
            
            Assert.That(bin.Range, Is.EqualTo(0));
        }

        [Test]
        public void DoesntAddRangedValuesOutsideOfStaticBounds()
        {
            var bin = new HistogramBin(2d);
            bin.Add(new[] { 4, 5, 6, 3, 1d });

            Assert.That(bin.Range, Is.EqualTo(0));
        }

        [Test]
        public void AddsSingleValueOutsideOfDynamicBounds()
        {
            var bin = new HistogramBin(2d, true);
            bin.Add(4);

            Assert.That(bin.Range, Is.EqualTo(2));
        }

        [Test]
        public void DoesntAddSingleValueOutsideOfStaticBounds()
        {
            var bin = new HistogramBin(2d);
            bin.Add(3);

            Assert.That(bin.Range, Is.EqualTo(0));
        }
    }
}
